package com.atguigu.gulimall.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.product.entity.*;
import com.atguigu.gulimall.product.feign.SeckillFeignService;
import com.atguigu.gulimall.product.service.*;
import com.atguigu.gulimall.product.vo.SeckillSkuInfoVo;
import com.atguigu.gulimall.product.vo.SkuItemVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.dao.SkuInfoDao;

import javax.annotation.Resource;


@Service("skuInfoService")
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService {

    @Resource
    private SpuInfoDescService spuInfoDescService;

    @Resource
    private SkuImagesService skuImagesService;

    @Resource
    private AttrGroupService attrGroupService;

    @Resource
    private SeckillFeignService seckillFeignService;

    @Resource
    private AttrAttrgroupRelationService attrAttrgroupRelationService;

    @Resource
    private ProductAttrValueService productAttrValueService;

    @Resource
    private SkuSaleAttrValueService skuSaleAttrValueService;

    @Resource
    private ThreadPoolExecutor executor;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                new QueryWrapper<SkuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryByConditionsPage(Map<String, Object> params) {
        QueryWrapper<SkuInfoEntity> wrapper = new QueryWrapper<>();

        String key = (String) params.get("key");
        if (StringUtils.isNotEmpty(key)){
            wrapper.and(w->w.eq("sku_id",key).or().like("sku_title",key).or().like("sku_subtitle",key));
        }

        String catelogId = (String) params.get("catelogId");
        if (StringUtils.isNotEmpty(catelogId) && Integer.parseInt(catelogId) != 0){
            wrapper.eq("catalog_id",catelogId);
        }

        String brandId = (String) params.get("brandId");
        if (StringUtils.isNotEmpty(brandId) && Integer.parseInt(brandId) != 0){
            wrapper.eq("brand_id",brandId);
        }

        String min = (String) params.get("min");
        if (StringUtils.isNotEmpty(min) && Integer.parseInt(min) != 0){
            wrapper.ge("price",min);
        }

        String max = (String) params.get("max");
        if (StringUtils.isNotEmpty(max) && Integer.parseInt(max) != 0){
            wrapper.le("price",max);
        }

        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public List<SkuInfoEntity> selectBySpuId(Long spuId) {
        return baseMapper.selectList(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId));
    }

    @Override
    public BigDecimal getPriceBySkuId(Long skuId) {
        SkuInfoEntity skuInfoEntity = baseMapper.selectById(skuId);
        return skuInfoEntity.getPrice();
    }

    @Override
    public SkuItemVo item(Long skuId) throws ExecutionException, InterruptedException {

        /**
         * 异步编排：
         * 第一二步谁先谁后无所谓，可以并行执行，
         * 但是三四五步都依赖于第一步查出来的spuId
         * 三四五步之间相互没有依赖关系
         */

        SkuItemVo skuItemVo = new SkuItemVo();

        //sku基本信息
        CompletableFuture<Void> infoCompletableFuture = CompletableFuture.runAsync(() -> {
            SkuInfoEntity skuInfoEntity = baseMapper.selectById(skuId);
            skuItemVo.setInfo(skuInfoEntity);
        });


        //sku图片信息
        CompletableFuture<Void> imgCompletableFuture = CompletableFuture.runAsync(() -> {
            List<SkuImagesEntity> images = skuImagesService.getBySkuId(skuId);
            skuItemVo.setImages(images);
        });


        //spu销售属性组合
        CompletableFuture<Void> skuAttrCompletableFuture = infoCompletableFuture.thenRunAsync(() -> {
            List<SkuItemVo.SkuItemSaleAttrVo> saleAttr =
                    skuSaleAttrValueService.getSkuItemSaleAttrVoBySpuId(skuItemVo.getInfo().getSkuId());
            skuItemVo.setSaleAttr(saleAttr);
        });


        //spu介绍
        CompletableFuture<Void> descCompletableFuture = infoCompletableFuture.thenRunAsync(() -> {
            SpuInfoDescEntity spuInfoDesc = spuInfoDescService.getById(skuItemVo.getInfo().getSpuId());
            skuItemVo.setDesc(spuInfoDesc);
        });


        //spu规格参数（分组属性及属性值）
        CompletableFuture<Void> spuAttrCompletableFuture = infoCompletableFuture.thenRunAsync(() -> {
            List<SkuItemVo.SpuItemAttrGroupVo> groupAttrs =
                    attrGroupService.getAttrWithGroupNameBySpuId(skuItemVo.getInfo().getSpuId());
            skuItemVo.setGroupAttrs(groupAttrs);
        });

        CompletableFuture<Void> seckillCompletableFuture = CompletableFuture.runAsync(() -> {
            //再查一下秒杀的信息
            R r = seckillFeignService.getSeckillSkuInfo(skuId);
            if (r.getCode() == 0) {
                List<SeckillSkuInfoVo> data = r.getData(new TypeReference<List<SeckillSkuInfoVo>>() {
                });
                //这里先简单处理，只取第一个
                skuItemVo.setSeckillSkuVo(data.get(0));
            }
        });


        //这里需要等前面的异步任务都执行完再返回，否则返回出去的skuItemVo信息会不全
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture
                .allOf(skuAttrCompletableFuture, descCompletableFuture, spuAttrCompletableFuture, imgCompletableFuture,seckillCompletableFuture);
        voidCompletableFuture.get();
        //这里用join行吗？
        //voidCompletableFuture.join();

        return skuItemVo;
    }
}